(实践部分)省流:吴恩达教授联合OpenAI制作的《面向开发者的ChatGPT提示工程》图文版笔记 - 掘金 即使并非本课程主要面向的开发者群体,也可通过本课程中实践部分的学习,得到思维上的启发,从而自己做出更多有意思的小项目。

近日,全球领先的 AI 教育平台 DeepLearning.ai 推出了一门全新的课程——《ChatGPT Prompt Engineering for Developers (面向开发者的 ChatGPT 提示工程)》

该课程由国际知名的 AI 领域权威学者吴恩达教授联合 OpenAI 一起制作,共 9 个课时。除去最后的课程总结,共可分为两个部分:

  1. 理论部分(第 1~3 章节)
  2. 实践部分(第 4~8 章节)

本文为下篇,主要内容是针对其实践部分的图文笔记记录,目的是促进学习者更高效、更有条理地记忆每个步骤中的重点

虽然实践部分要求有一定的代码能力,但在笔记中我会尽量淡化代码的部分,而更侧重于于梳理逻辑的部分。

因此,即使并非本课程主要面向的开发者群体,也可通过本课程中实践部分的学习,得到思维上的启发,从而自己做出更多有意思的小项目

(本文的思维导图与本课程的在线观看地址均在文末,可自取。)

Jupyter Notebook 网页程序的基本说明

不同于通过浏览器上的聊天界面直接与 ChatGPT 交互,本课程的主要目的是教授开发者掌握使用 API 快速构建应用程序的能力。不过,为了降低开发者的学习门槛,DeepLearning.ai 官网在课程视频的左侧嵌入了一个Jupyter Notebook网页程序。

Jupyter Notebook 网页程序可支持「实时代码运行」和「Markdown 笔记预览」,这样我们就可以直接在网页上运行 Python 代码了。实际上,即使是完全不懂代码的小白,只要点击 Jupyter Notebook 上的 “运行” 按钮,就可以立马看到代码运行的效果,从而可以快速验证调整输入或 Prompt 之后的执行结果

需要特别提到的是,在整个课程中,有 2 个单元格的内容始终贯穿在每个章节的 Jupyter Notebook 网页程序的开头。

第一个单元格用于设置我们自己的 OpenAI API 密钥,当然我们也可以不设置,这种情况下使用的就是网页提供的默认密钥。

第二个单元格是一个getCompletion函数,用于接受 Prompt 并返回对应的完成内容,可以简单认为就是和 ChatGPT 对话并返回结果的过程。

这两个单元格必须保证每次先运行过,后面的单元格才能运行正常。而要运行某个单元格也很简单,只需要鼠标选中单元格,然后点击 “运行” 按钮就可以了。

但需要注意的是,某个单元格的运行可能会依赖于前面另外一个单元格中设置的变量,因此对于完全不懂代码的小白来说,最好还是从头开始逐一运行每个单元格,直到到达想要验证执行结果的单元格,这样才能保证不会出错。

总结类提示词工程应用

每天我们都面临着大量的文字处理工作,遗憾的是我们并不能保证每次都有足够的时间来逐字逐句地完成阅读。幸运的是,大型语言模型的典型应用场景之一,就是处理这类需要概括文章 / 生成摘要的任务。

以 “总结商品评论” 为例,我们常常会收到这样一类评论:

为我女儿的生日买了这个熊猫毛绒玩具,她很喜欢它,并且会带着它去任何地方。 它柔软而超级可爱,它的脸看起来很友善。 虽然我付出的代价有点小。 我认为同样的价格可能还有其他更大的选择。 它比预期提前一天到达,所以在我把它送给她之前我必须自己玩它。

这类评论包含的信息点很多,有些甚至带有某种明显的情绪,但其中绝大多数文字对于内容的理解是没有任何帮助的。

于是,我们可以在 Prompt 中要求模型生成这条评论的简短摘要,并要求其限制摘要输出的字数:

您的任务是生成来自电子商务网站的产品评论的简短摘要。

总结下面用三重引号分隔的评论,最多 30 个单词。

执行结果如下:

Soft and cute panda plush toy loved by daughter, but a bit small for the price. Arrived early.

女儿喜欢的柔软可爱的熊猫毛绒玩具,但相对于价格来说玩具有点小。 早到了。

我们还可以进一步要求其生成的摘要侧重于哪方面内容,比如派送效率:

熊猫毛绒玩具比预期提前一天到货,但客户觉得相对于所支付的价格来说玩具有点小。

或者是价格合理程度:

熊猫毛绒玩具柔软、可爱,深受收件人的喜爱,但价格相对于它的尺寸来说可能太高了。

有时候,即便我们要求了侧重点,模型仍会输出其他方面的信息。这个时候,我们可以要求其 “提取” 信息而不是 “总结” 信息,如要求其只生成与派送效率相关的信息,这样就可以排除其他信息的干扰:

产品比预期提前一天到达。

通常情况下,商品评论会不止一条,这个时候,代码的优势就体现出来了,我们可以收集并总结多个商品评论,以有效了解所有用户的想法:

这两个单元格的代码大致含义是,定义了几个评论内容,并把这几个评论放到一个集合里,然后遍历这个集合,依次生成摘要并打印出摘要内容。

执行结果如下:

0 Soft and cute panda plush toy loved by daughter, but a bit small for the price. Arrived early.

1 Affordable lamp with storage, fast shipping, and excellent customer service. Easy to assemble and missing parts were quickly replaced.

2 Good battery life, small toothbrush head, but effective cleaning. Good deal if bought around $50.

3 Mixed review of a blender system with price gouging and decreased quality, but helpful tips for use.

0 女儿喜欢的柔软可爱的熊猫毛绒玩具,但相对价格来说玩具有点小。 早到了。

1 经济实惠的灯具有存储、快速运输和卓越的客户服务。 易于组装,缺少的零件可以快速更换。

2 电池寿命长,牙刷头小,但清洁效果好。 如果在 50 美元左右购买,很划算。

3 对价格欺诈和质量下降的搅拌机系统的混合评论,但有用的使用提示。

推理类提示词工程应用

识别文本的情感

使用大型语言模型来识别一段文本中包含的情感是很容易的,我们所要做的就只是编写一个 Prompt,而不需要像传统机器学习那样训练和部署模型。

同样以商品评论为例,现在,让我们编写一个 Prompt 来要求模型识别以下评论的情感:

我的卧室需要一盏漂亮的灯,这盏灯有额外的储物空间,而且价格不太高。 很快就知道了。 我们的灯在运输过程中断了,公司很高兴地送来了一根新的。 几天之内也来了。 很容易放在一起。 我有一个缺失的部分,所以我联系了他们的支持,他们很快就帮我找到了缺失的部分! 在我看来,Lumina 是一家关心客户和产品的伟大公司!

以下用三重引号分隔的产品评论的情感是什么?

模型反馈说,这个评论的情感是积极的。这没错,但我们希望其用单一的词语来形容这种情感,从 “积极的” 或“消极的”这两个词中二选其一:

但是积极或消极的形容词还是过于笼统,我们可以要求其列表形式来识别包含的具体情感:

快乐、满意、感激、感动、满足

作为商家,我们通常会更关注差评,为此,我们可以要求其判断评论中是否表达了愤怒的情感:

以下评论的作者是否表达了愤怒?评论用三重引号分隔。给出是或否的答案。

否。

提取信息

自然语言处理 (NLP) 中的「信息提取」,是指从文本中提取出你关心的部分内容。比如,在以下 Prompt 中,我们要求模型提取评论中提及的商品及其制造商,并以 JSON 形式输出:

推断主题

大型语言模型还有一个典型的应用场景就是推断主题:给定一段长文本,推断出这段文本的内容是关于什么的,都包含哪些主题。

例如下面这一篇虚构的新闻,我们可以要求模型推断出文章讨论的几个主题:

在政府最近进行的一项调查中,公共部门雇员被要求对他们的水平进行评分 对他们工作的部门的满意度。 结果显示,NASA 是最受欢迎的部门,满意度为 95%。

美国国家航空航天局的一名员工约翰 · 史密斯对调查结果发表了评论,他说:“我对美国国家航空航天局名列前茅并不感到惊讶。这是一个与了不起的人和难以置信的机会一起工作的好地方。我很自豪能成为其中的一员 一个创新的组织。”

结果也受到 NASA 管理团队的欢迎,主任汤姆约翰逊表示:“我们很高兴听到我们的员工对他们在 NASA 的工作感到满意。我们拥有一支才华横溢且敬业的团队,他们为实现我们的目标而不懈努力,这是 很高兴看到他们的辛勤工作得到回报。”

调查还显示,社会保障局的满意度最低,只有 45% 的员工表示对自己的工作感到满意。 政府已承诺解决员工在调查中提出的担忧,并努力提高所有部门的工作满意度。

确定以下由三个引号分隔的文本中讨论的五个主题。

让每个项目一两个词长。

将你的回复格式化为以逗号分隔的项目列表。

如果我们想弄清楚在给定的新闻文章中,是否包含了部分特定的主题,我们可以要求模型判断指定的某几个主题是否在文章中出现:

确定以下主题列表中的每一项是否是以下文本中的主题,该文本由三重引号分隔。 以列表的形式给出你的答案,每个主题用 0 或 1。

执行结果如下:

nasa: 1

local government: 0

engineering: 0

employee satisfaction: 1

federal government: 1

通过这种主题的推断并归类,我们可以很快速的找到该主题分类下的相关文章。

转换类提示工程应用

大型语言模型非常擅长将其输入转换为不同的格式,比如翻译、拼写检查 / 语法纠正以及结构化输出 (JSON) 等工作。

翻译

大型语言模型接受了来自互联网的大量文本训练,这些文本中包含了不同的语言,因此,翻译能力可以说是模型最基础的能力了。

例如,最简单的,我们可以要求其将以下的英文翻译成西班牙文:

反过来,我们也可以要求其识别以下是什么语言:

与传统翻译不同的是,我们还可以要求其分别以正式和非正式形式进行翻译,以应对不同场合的需要:

现在,假设我们是一家跨国公司,用户发来的信息可能是各种不同的语言,因此,我们需要一个万能的翻译器,这个翻译器要求:

  1. 能识别问题所使用的语言
  2. 打印出原始消息中问题
  3. 将其分别翻译成英语和韩语

我们把这些要求转化到 Prompt 中,即如下:

这两个单元格代码的含义,也是先定义了一个问题文本集合,然后遍历这个集合中的每个问题,针对每个问题依次先打印原始内容,接着翻译成英语和韩语。

执行结果如下:

Original message (This is French.): La performance du système est plus lente que d'habitude.
English: The system performance is slower than usual.
Korean: 시스템 성능이 평소보다 느립니다. 

Original message (This is Spanish.): Mi monitor tiene píxeles que no se iluminan.
English: My monitor has pixels that don't light up.
Korean: 내 모니터에는 불이 켜지지 않는 픽셀이 있습니다. 

Original message (This is Italian.): Il mio mouse non funziona
English: My mouse is not working.
Korean: 내 마우스가 작동하지 않습니다. 

Original message (This is Polish.): Mój klawisz Ctrl jest zepsuty
English: My Ctrl key is broken.
Korean: 제 Ctrl 키가 고장 났어요. 

Original message (This is Chinese (Simplified).): 我的屏幕在闪烁
English: My screen is flickering.
Korean: 내 화면이 깜빡입니다.

结构化输出

ChatGPT 非常擅长在不同格式之间进行转换,我们前面已经见识到了其文本转 JSON 的能力了,现在,我们再来验证一下其 JSON 转 HTML 表格的能力。

首先,我们需要在 Prompt 中,描述其输入和输出的格式,这里是从 JSON 转换为 HTML:

输出结果如下:

<table>
  <caption>Restaurant Employees</caption>
  <thead>
    <tr>
      <th>Name</th>
      <th>Email</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Shyam</td>
      <td>[email protected]</td>
    </tr>
    <tr>
      <td>Bob</td>
      <td>[email protected]</td>
    </tr>
    <tr>
      <td>Jai</td>
      <td>[email protected]</td>
    </tr>
  </tbody>
</table>

上面我们看到的结果实际是被 HTML 标签包裹的文本,因此还需要使用 Python 库中的显示函数来显示成 HTML 表格:

拼写检查 / 语法纠正

使用 ChatGPT 进行拼写检查和语法纠正是一种非常流行的用法,特别当你在非母语环境中工作时,会非常有用。

我们可以在输入待检查的文本后,要求其校对和纠正指定文本,并重写整个校正版本:

输出结果如下:

The girl with the black and white puppies has a ball.

No errors found.

It's going to be a long day. Does the car need its oil changed?

Their goes my freedom. There going to bring they're suitcases.

Corrected version: There goes my freedom. They're going to bring their suitcases.

You're going to need your notebook. That medicine affects my ability to sleep. Have you heard of the butterfly effect? This phrase is to check ChatGPT for spelling ability.

为了获取评论的原始文本和模型输出之间的差异,我们还可以使用这个 RedLines Python 包来将修改的地方进行高亮显示:

拓展类提示词工程应用

扩充是一项将简短文本片段转换为更长文本的任务,在写邮件或写论文的时候会经常用到,也常有人将其用于头脑风暴。

接下来我们将演示如何要求模型基于客户评论及评论情绪生成回复邮件:

你是客服 AI 助理。

您的任务是向尊贵的客户发送电子邮件回复。

给定以 ``` 分隔的客户电子邮件,生成回复以感谢客户的评论。

如果情绪是积极的或中立的,感谢他们的评论。

如果情绪是负面的,请道歉并建议他们联系客户服务。

确保使用评论中的具体细节。

以简洁和专业的语气写作。

将电子邮件签名为 “AI 客服”。

执行的结果如下:

Dear Valued Customer,

Thank you for taking the time to leave a review about our product. We are sorry to hear that you experienced an increase in price and that the quality of the product did not meet your expectations. We apologize for any inconvenience this may have caused you.

We would like to assure you that we take all feedback seriously and we will be sure to pass your comments along to our team. If you have any further concerns, please do not hesitate to reach out to our customer service team for assistance.

Thank you again for your review and for choosing our product. We hope to have the opportunity to serve you better in the future.

Best regards,

AI customer agent

尊贵的顾客,

感谢您抽出宝贵时间对我们的产品发表评论。 我们很遗憾听到您遇到价格上涨并且产品质量没有达到您的期望。 对于由此给您带来的任何不便,我们深表歉意。

我们向您保证,我们会认真对待所有反馈,并且一定会将您的意见转达给我们的团队。 如果您有任何其他疑虑,请随时联系我们的客户服务团队寻求帮助。

再次感谢您的评论和选择我们的产品。 我们希望将来有机会为您提供更好的服务。

此致,

AI 客服

这个过程中还使用到了另一个模型输入参数,称为Temperature,中文直译为 “温度”。

这个参数代表的是模型回应的多样性程度,你可以简单认为就是回答内容的随机化程度:

例如,当回答 “我的最爱食物是……” 这个问题时,不同食物出现的可能性不同。当 Temperature 为 0 时,模型总会选择其中最有可能的一个,即披萨。而当 Temperature 为 0.3 时,模型才有可能选择可能性较低其他食物。当 Temperature 为 0.7 时,模型才有可能选择更低可能性的其他食物。

(如果你有使用过 New Bing 的话,应该会对这个参数的含义更加熟悉。)

构建聊天机器人

ChatGPT 这个的聊天模型实际就是被训练成以一系列消息作为输入,并返回模型生成的消息作为输出的。借助大型语言模型,我们也可以很容易地通过定义聊天格式或指定任务内容的方式,构建出定制化的聊天机器人

但在构建之前,我们需要先理清一个消息列表中所包含的不同角色消息。

messages =  [  
{'role':'system', 'content':'You are an assistant that speaks like Shakespeare.'},    
{'role':'user', 'content':'tell me a joke'},   
{'role':'assistant', 'content':'Why did the chicken cross the road'},   
{'role':'user', 'content':'I don\'t know'}  ]

首先第一条消息是「系统消息」,它提供了一个整体的指导;

在这条消息之后,是「用户消息」和「助手消息」。如果你有使用过 ChatGPT 在浏览器上的聊天界面,那么你发出的消息就是用户消息,ChatGPT 回复的消息就是助手消息。

系统消息无疑是其中最重要的角色消息,其有助于塑造助手的行为和形象,作为一种高级指令来帮助对话。你可以把它看作是在助手的耳边讲悄悄话的人,引导助手的回答,而用户并不知道系统消息的存在

接下来我们再来了解一个新的辅助函数,这个辅助函数与之前的辅助函数的区别主要在于以下两点:

def get_completion_from_messages(messages, model="gpt-3.5-turbo", temperature=0):
    response = openai.ChatCompletion.create(
        model=model,
        messages=messages,
        temperature=temperature, # this is the degree of randomness of the model's output
    )
#     print(str(response.choices[0].message))
    return response.choices[0].message["content"]

Temperature 参数我们前面已经介绍过了。而之所以要提供早期的交流信息,是因为与语言模型的每次交谈实际都是独立的交互,因此我们必须提供所有相关的信息,以便模型能在理解前期对话内容的前提下,在当前会话中继续之前的话题

这种早期的交流信息,我们称之为「上下文」。很明显,这种上下文会随着时间的推移而不断增加

接下来,我们将以披萨餐厅订单机器人为例,演示构建聊天机器人的整体流程。

步骤 1:构建 GUI

第一步我们要做的就是构建一个类似于 ChatGPT 聊天界面的 GUI(图形用户界面),布局从上到下排列依次是输入框,发送按钮和消息列表,并且为发送按钮添加了交互效果:

每次点击发送按钮都会收集输入框内容和模型响应结果,然后添加到消息列表。

import panel as pn
pn.extension()

panels = []

# 输入框,输入提示是'Enter text here…'
inp = pn.widgets.TextInput(value="Hi", placeholder='Enter text here…')
# 发送按钮,按钮文本是"Chat!"
button_conversation = pn.widgets.Button(name="Chat!")

# 消息列表,与发送按钮绑定,每次点击发送按钮都会调用collect_messages方法
interactive_conversation = pn.bind(collect_messages, button_conversation)

# 按纵向布局排列
dashboard = pn.Column(
    inp,
    pn.Row(button_conversation),
    pn.panel(interactive_conversation, loading_indicator=True, height=300),
)

dashboard

# 收集输入框内容和模型响应结果,添加到消息列表
def collect_messages(_):
    # 提取输入框内容
    prompt = inp.value_input
    # 清空输入框内容
    inp.value = ''
    # 追加一条用户消息(输入框填写的内容)到上下文
    context.append({'role':'user', 'content':f"{prompt}"})
    # 请求模型响应结果
    response = get_completion_from_messages(context) 
    # 追加一条助手消息(模型的响应结果)到上下文
    context.append({'role':'assistant', 'content':f"{response}"})
    # 追加一个用户消息行到消息列表
    panels.append(
        pn.Row('User:', pn.pane.Markdown(prompt, width=600)))
    # 追加一个助手消息行到消息列表    
    panels.append(
        pn.Row('Assistant:', pn.pane.Markdown(response, width=600, style={'background-color': '#F6F6F6'})))
 
    return pn.Column(*panels)

步骤 2. 提供上下文

这一步我们将提供上下文,并以系统消息的角色告诉它:

你是一个负责自动化收集比萨饭店订单的订单机器人。 你首先需要问候客户,然后收集订单信息,然后询问是自取或配送等等。

context = [ {'role':'system', 'content':"""
You are OrderBot, an automated service to collect orders for a pizza restaurant. \
You first greet the customer, then collects the order, \
and then asks if it's a pickup or delivery. \
You wait to collect the entire order, then summarize it and check for a final \
time if the customer wants to add anything else. \
If it's a delivery, you ask for an address. \
Finally you collect the payment.\
Make sure to clarify all options, extras and sizes to uniquely \
identify the item from the menu.\
You respond in a short, very conversational friendly style. \
The menu includes \
pepperoni pizza  12.95, 10.00, 7.00 \
cheese pizza   10.95, 9.25, 6.50 \
eggplant pizza   11.95, 9.75, 6.75 \
fries 4.50, 3.50 \
greek salad 7.25 \
Toppings: \
extra cheese 2.00, \
mushrooms 1.50 \
sausage 3.00 \
canadian bacon 3.50 \
AI sauce 1.50 \
peppers 1.00 \
Drinks: \
coke 3.00, 2.00, 1.00 \
sprite 3.00, 2.00, 1.00 \
bottled water 5.00 \
"""} ]  # accumulate messages

3. 收集订单信息

这一步就是通过与客户的持续对话来收集订单信息,然后进行总结确认,并询问客户是否还需要添加其他商品。如果提交订单,会要求客户提供地址。最后,接受客户的付款。

这里每一步的对话内容都会添加到上下文中,并传回给模型。

4. 生成订单摘要,发送到订购系统

最后这一步就是当订单信息收集完毕之后,生成一个 JSON 格式的订单摘要,然后发送到订购系统,完成下单。

messages =  context.copy()
messages.append(
{'role':'system', 'content':'create a json summary of the previous food order. Itemize the price for each item\
 The fields should be 1) pizza, include size 2) list of toppings 3) list of drinks, include size   4) list of sides include size  5)total price '},    
)
 #The fields should be 1) pizza, price 2) list of toppings 3) list of drinks, include size include price  4) list of sides include size include price, 5)total price '},    

response = get_completion_from_messages(messages, temperature=0)
print(response)

课程总结

在最后的这一章节,让我们用魔法来打败魔法,也即基于本课程在第 4 章节的 Jupyter Notebook 网页程序中提供的演示代码,进行修改后来总结这一章节的内容。

输出的结果如下:

这门短期课程主要介绍了两个关键的提示原则:编写清晰明确的指令和在适当的时候给模型一些时间来思考。

同时,还学习了迭代提示开发的过程,以及如何构建自定义聊天机器人。

此外,课程还介绍了大型语言模型的几个有用功能,包括摘要、推断、转换和扩展。

最后,强调了使用这些工具时需要负责任,只构建对他人有积极影响的应用。完成这门课程后,学习者可以尝试构建自己的应用,并将所学知识传播给他人。

最后的最后,我们将本文的所有内容总结成了以下这张思维导图,可在线收藏或保存到本地:

对课程感兴趣,想直接线上观看学习的同学,也可以上 DeepLearning.ai 的官网免费观看:

learn.deeplearning.ai/chatgpt-pro…

创作不易,还请大家多多点赞分享,Thanks♪(・ω・)ノ~

Jupyter Notebook 网页程序的基本说明总结类提示词工程应用推理类提示词工程应用识别文本的情感提取信息推断主题转换类提示工程应用翻译结构化输出拼写检查 / 语法纠正拓展类提示词工程应用构建聊天机器人步骤 1:构建 GUI步骤 2. 提供上下文3. 收集订单信息4. 生成订单摘要,发送到订购系统课程总结 全文完
本文由 简悦 SimpRead 转码,用以提升阅读体验,原文地址